package mygame.chameleonpoker;

import java.util.Random;

import mygame.chameleonpoker.GameScreen.RoundState;
import mygame.chameleonpoker.PokerCards.Card;

public class Computer extends Player {
	
	Random rand = new Random();

	public void process(Card currentCard, RoundState roundstate, PokerCards pokercards) {
		
		// when the current card is null, means computer 1 is the first one to lead card
		if(currentCard.is_null()) {
			if(find_the_biggest_number().number == 11 || find_the_biggest_number().number == 12) 
				lead_card(get_cards().indexOf(find_the_biggest_number()));
			else 
				lead_card(get_cards().indexOf(find_the_most_pattern()));
			 
			if(roundstate.state == RoundState.Computer1Lead)
				roundstate.state = RoundState.Computer2Lead;
			else
				roundstate.state = RoundState.PlayerLead;
			currentCard.Copy(get_leaded_card());
			return;
		}
		
		/* when the current card is existed */
		
		// if there is a card that is equal to the number of the current card, lead it and change the pattern to
		// the most popular pattern among the rest of the cards
		for(int i = 0; i < get_numb_of_cards(); i++) {
			if(get_cards().get(i).number == currentCard.number) {
				lead_card(get_cards().indexOf(get_cards().get(i)));
				 
				if(roundstate.state == RoundState.Computer1Lead)
					roundstate.state = RoundState.Computer2Lead;
				else
					roundstate.state = RoundState.PlayerLead;
				currentCard.pattern = find_the_most_pattern().pattern;
				return;
			}
		}
		
		// when there is matched card existed
		if(find_card_accordingly(currentCard) != null) {
			if(pokercards.get_number() == 0 ||
			find_num_of_card_accordingly(currentCard) >=2 || 
			(find_the_smallest_number().number == find_card_accordingly(currentCard).number && num_more_than_one(find_the_smallest_number().number))|| 
			find_card_accordingly(currentCard).number > 8 ||
			find_the_smallest_number().number <= find_card_accordingly(currentCard).number) {
					lead_card(get_cards().indexOf(find_card_accordingly(currentCard)));
					 
					if(roundstate.state == RoundState.Computer1Lead)
						roundstate.state = RoundState.Computer2Lead;
					else
						roundstate.state = RoundState.PlayerLead;
					currentCard.Copy(get_leaded_card());
					return;
				}
		}
		
		// if there are not pattern-matched or number-equaled cards, check if there is J
		for(int i = 0; i < get_numb_of_cards(); i++) {
			if(get_cards().get(i).number == 10) {
				lead_card(get_cards().indexOf(get_cards().get(i)));
				 
				if(roundstate.state == RoundState.Computer1Lead)
					roundstate.state = RoundState.Computer2Lead;
				else
					roundstate.state = RoundState.PlayerLead;
				currentCard.pattern = find_the_most_pattern().pattern;
				currentCard.number = -1;
				return;
			}
		}
		
		// if there is still no J, find if there is Joker
		for(int i = 0; i < get_numb_of_cards(); i++) {
			if(get_cards().get(i).pattern == Card.Joker) {
				if(find_the_biggest_number().number < 5) {
					lead_card(get_cards().indexOf(get_cards().get(i)));
					 
					if(roundstate.state == RoundState.Computer1Lead)
						roundstate.state = RoundState.Computer2Lead;
					else
						roundstate.state = RoundState.PlayerLead;
					currentCard.number = -1;
					return;
				}
			}
		}
		
		// if the program reach here, the only choice is to select the smallest card to bury
		bury_card(get_cards().indexOf(find_the_smallest_number()));
		if(pokercards.get_number()!=0)
			set_wait_status(true);
		if(roundstate.state == RoundState.Computer1Lead)
			roundstate.state = RoundState.Computer2Lead;
		else
			roundstate.state = RoundState.PlayerLead;
		return;
	}
	
	// find a card that with the biggest number and most popular pattern
	public Card find_the_most_pattern() {
		int pattern[] = new int[4];
		int max = -200;
		int index = 0;
		int location = 0;
		
		if(get_numb_of_cards() == 0) {
			Card card = new Card();
			card.pattern = rand.nextInt(4);
			return card;
		}	
		
		for(int i = 0; i < get_numb_of_cards(); i++) {
			if(get_cards().get(i).pattern == Card.Spade && get_cards().get(i).number != 10)
				pattern[0]++;
			if(get_cards().get(i).pattern == Card.Heart && get_cards().get(i).number != 10)
				pattern[1]++;
			if(get_cards().get(i).pattern == Card.Club && get_cards().get(i).number != 10)
				pattern[2]++;
			if(get_cards().get(i).pattern == Card.Diamond && get_cards().get(i).number != 10)
				pattern[3]++;
		}
		
		for(int i = 0; i < 4; i++) {
			if(pattern[i]>=max) {
				max = pattern[i];
				index = i;
			}	
		}
		
		max = -200;
		
		for(int i = 0; i < get_numb_of_cards(); i++) {
			if(get_cards().get(i).pattern == index) {
				if(get_cards().get(i).number >= max && get_cards().get(i).number != 10) {
					max = get_cards().get(i).number;
					location = i;
				}
			}
		}
		return get_cards().get(location);
	}
	
	// find a card with the biggest number
	public Card find_the_biggest_number() {
		int max = -200;
		int location = 0;
		for(int i = 0; i < get_numb_of_cards(); i++) {
			if(get_cards().get(i).pattern != Card.Joker && get_cards().get(i).number != 10) {
				if(get_cards().get(i).number >= max) {
					max = get_cards().get(i).number;
					location = i;
				}
			}
		}
		return get_cards().get(location);
	}
	
	// find a card with the smallest number to bury
	public Card find_the_smallest_number() {
		int min = 200;
		int location = 0;
		for(int i = 0; i < get_numb_of_cards(); i++) {
			
			if(get_cards().get(i).pattern == Card.Joker)
				return get_cards().get(i);
			
			if(get_cards().get(i).number != 10) {
				if(get_cards().get(i).number <= min) {
					min = get_cards().get(i).number;
					location = i;
				}
			}
		}
		return get_cards().get(location);
	}
	
	// find the biggest card according to the current card's pattern
	public Card find_card_accordingly(Card card) {
		int max = -200;
		int location = -1;
		
		for(int i = 0; i < get_numb_of_cards(); i++) {
			if(get_cards().get(i).pattern == card.pattern && get_cards().get(i).number != 10) {
				if(get_cards().get(i).number >= max) {
					max = get_cards().get(i).number;
					location = i;
				}
			}
		}
		if(location == -1)
			return null;
		else
			return get_cards().get(location);
	}
	
	// find number of card that has the small pattern with the given card
	public int find_num_of_card_accordingly(Card card) {
		int num = 0;
		
		for(int i = 0; i < get_numb_of_cards(); i++)
			if(get_cards().get(i).pattern == card.pattern && get_cards().get(i).number != 10)
					num++;
		return num;
	}
	
	public boolean num_more_than_one(int number) {
		int count = 0;
		for(int i = 0; i < get_numb_of_cards(); i++) {
			if(get_cards().get(i).number == number) 
				count++;
		}
		if(count >=2)
			return true;
		return false;
		
	}
}
